package subgroup

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"fmt"
	mrand "math/rand"
	"strings"
	"time"
)

var sz = "0123456789abcdefghijklmnopqrstuvwxyz"
var bsz = []byte(sz)
var szLen = len(sz)

func getTicketId() string {
	ticketID := make([]byte, 10)
	for i := 0; i < 10; i++ {
		p := mrand.Intn(szLen)
		ticketID[i] = bsz[p]
	}
	return string(ticketID)
}

func getserverUid() string {
	serverUID := ""
	certStr, _ := base64.StdEncoding.DecodeString(LicenseCertStr)
	cert, _ := x509.ParseCertificate(certStr)
	name := cert.Subject.CommonName
	names := strings.Split(name, ".")
	if len(names) > 0 {
		serverUID = names[0]
	}
	return serverUID
}

func getLeaseSignature(leaseContent string) string {
	tKey, _ := base64.StdEncoding.DecodeString(JetBraninsPrivateKey)
	mPrivateKey, _ := x509.ParsePKCS1PrivateKey(tKey)
	signature, _ := signContent([]byte(leaseContent), mPrivateKey, crypto.SHA512)
	return "SHA512withRSA-" + signature + "-" + JetBraninsCertStr
}

func getConfirmationStamp(machineID string) string {
	mtime := time.Now().UnixNano() / int64(time.Millisecond)
	tKey, _ := base64.StdEncoding.DecodeString(LicensePrivateKey)
	licensePrivateKey, _ := x509.ParsePKCS1PrivateKey(tKey)
	signStr := fmt.Sprintf("%d:%s", mtime, machineID)
	signature, err := signContent([]byte(signStr), licensePrivateKey, crypto.SHA1)
	if err != nil {
		return ""
	}
	bsrt := fmt.Sprintf("%d:%s:SHA1withRSA:%s:%s", mtime, machineID, signature, LicenseCertStr)
	return bsrt
}

func getSignXml(xmlStr string) string {
	tKey, _ := base64.StdEncoding.DecodeString(LicensePrivateKey)
	licensePrivateKey, _ := x509.ParsePKCS1PrivateKey(tKey)
	sd, _ := signContent([]byte(xmlStr), licensePrivateKey, crypto.SHA1)
	return "<!-- SHA1withRSA-" + sd + "-" + LicenseCertStr + " -->\n" + xmlStr
}

func signContent(buf []byte, key *rsa.PrivateKey, hash crypto.Hash) (string, error) {
	hf := hash.New()
	hf.Write(buf)
	hashed := hf.Sum(nil)
	rBuf, err := rsa.SignPKCS1v15(rand.Reader, key, hash, hashed)
	if err != nil {
		return "", err
	}
	ret := base64.StdEncoding.EncodeToString(rBuf)
	return ret, nil
}
